import 'package:flutter/material.dart';

///
/// 头像叠加小部件
///
class XOverlayImage extends StatefulWidget {
  const XOverlayImage({
    super.key,
  });

  @override
  State<XOverlayImage> createState() => _XOverlayImageState();
}

class _XOverlayImageState extends State<XOverlayImage> with SingleTickerProviderStateMixin {
  // 图片叠加在一起的比率
  final double overlayRatio = 0.5;
  // 图片的宽高
  final double imageWidth = 50;
  final double imageHeight = 50;
  // 头像图片urls
  final List<String> imageUrls = [
    'https://img0.baidu.com/it/u=342860928,1412318868&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
    'https://img2.baidu.com/it/u=1397509398,2387330504&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
    'https://img0.baidu.com/it/u=2813615266,310539752&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
    'https://img1.baidu.com/it/u=487733523,2537255568&fm=253&fmt=auto&app=120&f=JPEG?w=502&h=500',
    'https://img2.baidu.com/it/u=400653519,2741143345&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
    'https://img0.baidu.com/it/u=1935047726,2391336384&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
    'https://img0.baidu.com/it/u=2510258447,3149796636&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
  ];
  List<String> _currentImages = []; // 用于存放切换图片的数组
  int _currentIndex = 0;

  // 添加动画
  late final AnimationController _animationController;
  late final Animation<double> _animation;

  // 计算存放头像图片的容器宽度；高度=50
  double get overlayImageContentWidth {
    return imageWidth * imageUrls.length - imageWidth * (1 - overlayRatio) * imageUrls.length;
  }

  // 处理头像的透明度
  double _opacity(int index) {
    if (index == 0) {
      return 1 - _animation.value; // 第一张图片，从不透明 -> 透明
    } else if (index == _currentImages.length - 1) {
      return _animation.value; // 最后一张图片，从透明 -> 不透明
    }
    return 1;
  }

  @override
  void initState() {
    super.initState();
    // take函数：返回值为 Iterable，参数为从索引 0 位置处，取多少个元素。
    _currentImages = imageUrls.take(imageUrls.length).toList();

    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );
    _animation = Tween<double>(begin: 0, end: 1).animate(_animationController)
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          // 根据当前 index，获取下一张index，然后获取新的图片，再进行 setState()，这样就能做到图片的切换
          setState(() {
            _currentIndex = (_currentIndex + 1) % imageUrls.length;
            _currentImages.removeAt(0);
            _currentImages.add(imageUrls[_currentIndex]);
          });

          _animationController.reset();

          Future.delayed(
            const Duration(seconds: 1),
            () {
              // mounted：因为此处利用了延迟执行，防止_animationController.dispose()后，forward()还在执行
              if (mounted) {
                _animationController.forward();
              }
            },
          );
        }
      });

    Future.delayed(
      const Duration(seconds: 1),
      () => _animationController.forward(),
    );
  }

  @override
  void dispose() {
    _animationController.stop();
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('XOverlayImage'),
      ),
      body: Center(
        child: SizedBox(
          width: overlayImageContentWidth,
          height: imageHeight,
          child: Stack(
            clipBehavior: Clip.none, // 超出部分不进行剪裁，使得最后一张图片不会被剪裁
            children: _buildOverlayImages(),
          ),
        ),
      ),
    );
  }

  List<Widget> _buildOverlayImages() {
    List<Widget> stackChildren = [];

    for (int i = 0; i < _currentImages.length; i++) {
      // 每涨图片的 x 位置
      double leftOffsetX = i * (imageWidth * overlayRatio);

      stackChildren.add(AnimatedBuilder(
        animation: _animation,
        builder: (context, child) {
          return Positioned(
            left: leftOffsetX - (_animation.value * imageWidth * overlayRatio),
            child: Opacity(
              opacity: _opacity(i),
              child: child!,
            ),
          );
        },
        child: ClipOval(
          key: ValueKey<String>(_currentImages[i]),
          child: Image.network(
            _currentImages[i],
            width: imageWidth,
            height: imageHeight,
            fit: BoxFit.cover,
          ),
        ),
      ));
    }

    return stackChildren;
  }
}
